package com.threeti.jiayusms.framework.web;

import static com.threeti.jiayusms.framework.util.CommonWebUtils.LOOKUP_PATH_FOR_REQUEST;
import static com.threeti.jiayusms.framework.util.CommonWebUtils.ORIGINATING_DECODED_URL;
import static com.threeti.jiayusms.framework.util.CommonWebUtils.ORIGINATING_QUERY_STRING;
import static com.threeti.jiayusms.framework.util.CommonWebUtils.getLookupPathForRequest;
import static com.threeti.jiayusms.framework.util.CommonWebUtils.getOriginatingDecodedURL;
import static com.threeti.jiayusms.framework.util.CommonWebUtils.getOriginatingQueryString;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.threeti.jiayusms.framework.util.PagedListHandler;

/**
 * 一个简单分页查询请求控制器基类<p/>
 *
 * @author Jay Meng
 */
public class PagedQueryControllerAdapter<T extends Object> implements Controller {
  public static final String EX_MSG = "分页查询数据返回了null，您如果将PagedQueryControllerHelper作为工具类使用，请手工设置firstPage";
  private static final Logger logger = LoggerFactory.getLogger(PagedQueryControllerAdapter.class);

  public static final int TARGET_PAGE_INDEX = 0;
  public static final int RECORD_START_INDEX = 1;

  private String successView;
  private boolean isShowPageArea = true;
  private PagedListHandler currentPage;

  public PagedQueryControllerAdapter() {
  }

  public PagedQueryControllerAdapter(String successView) {
    this.successView = successView;
  }

  public final void setSuccessView(String successView) {
    this.successView = successView;
  }

  public void setIsShowPageArea(boolean isShowPageArea) {
    this.isShowPageArea = isShowPageArea;
  }

  @Override
  public final ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) {
    logger.debug("handleRequest(HttpServletRequest, HttpServletResponse) - start");

    if (isFirstPage(request)) {
      PagedListHandler firstPage = processPage(request, response, 0, 0);
      Assert.notNull(firstPage, EX_MSG);

      postProcessPage(request, null, firstPage, true);
    } else {
      int[] pageInfo = preProcessPage(request);

      PagedListHandler anotherPage = processPage(request, response, pageInfo[TARGET_PAGE_INDEX], pageInfo[RECORD_START_INDEX]);
      Assert.notNull(anotherPage, EX_MSG);

      postProcessPage(request, pageInfo, anotherPage, false);
    }

    logger.debug("handleRequest(HttpServletRequest, HttpServletResponse) - end");
    return new ModelAndView(successView);
  }

  /** 作分页查询的前置处理 */
  protected final int[] preProcessPage(HttpServletRequest request) {
    logger.debug("preProcessPage(HttpServletRequest) - start");

    int currentPageIndex = 0;
    int currentRecordStartIndex = 0;
    String pageDirection = request.getParameter("pageDirection");

    if (request.getParameterValues("nextPageIndex").length == 1) {
      currentPageIndex = Integer.parseInt(request.getParameter("nextPageIndex"));
      currentRecordStartIndex = Integer.parseInt(request.getParameter("recordStartIndex"));

    } else {
      if ("previous".equals(pageDirection)) {
        currentPageIndex = Integer.parseInt(request.getParameterValues("nextPageIndex")[0]);
        currentRecordStartIndex = Integer.parseInt(request.getParameterValues("recordStartIndex")[0]);

      } else if("next".equals(pageDirection)) {
        currentPageIndex = Integer.parseInt(request.getParameterValues("nextPageIndex")[1]);
        currentRecordStartIndex = Integer.parseInt(request.getParameterValues("recordStartIndex")[1]);
      }
    }

    logger.debug("preProcessPage(HttpServletRequest) - end");
    return new int[] { currentPageIndex, currentRecordStartIndex };
  }

  protected final void postProcessPage(HttpServletRequest request, int[] pageInfo, PagedListHandler pListHandler, boolean isFirstPage) {
    logger.debug("postProcessPage(HttpServletRequest, int[], PagedListHandler, boolean) - start");

    int[] pageArea = null;
    if (isFirstPage) {
      request.setAttribute("previousPageIndex", 0);
      request.setAttribute("nextPageIndex", 1);
      request.setAttribute("previousRecordStartIndex", 0);
      request.setAttribute("nextRecordStartIndex", pListHandler.getPageSize());
      request.setAttribute("isFirstPage", true);
      request.setAttribute("isLastPage", pListHandler.isLastPage());

      if (isShowPageArea) pageArea = pListHandler.getPageShowArea(1);

    } else {
      int currentPageIndex = pageInfo[TARGET_PAGE_INDEX];
      int currentRecordStartIndex = pageInfo[RECORD_START_INDEX];

      request.setAttribute("nextPageIndex", currentPageIndex+1);
      request.setAttribute("nextRecordStartIndex", currentRecordStartIndex + pListHandler.getPageSize());

      request.setAttribute("previousPageIndex", currentPageIndex-1);
      request.setAttribute("previousRecordStartIndex", currentRecordStartIndex - pListHandler.getPageSize());

      request.setAttribute("isFirstPage", pListHandler.isFirstPage());
      request.setAttribute("isLastPage", pListHandler.isLastPage());

      if (isShowPageArea) pageArea = pListHandler.getPageShowArea(currentPageIndex+1);
    }

    if (isShowPageArea) request.setAttribute("pageArea", pageArea);

    request.setAttribute("hasNextPageArea", pListHandler.hasNextPageArea());
    request.setAttribute("hasPreviousPageArea", pListHandler.hasPreviousPageArea());
    request.setAttribute("pageCount", pListHandler.getPageCount());
    request.setAttribute("pageSize", pListHandler.getPageSize());

    String originatingDecodedURL = getOriginatingDecodedURL(request, true);
    String lookupPathForRequest = getLookupPathForRequest(request, true);
    String originatingQueryString = getOriginatingQueryString(request);
    
    request.setAttribute(ORIGINATING_DECODED_URL, originatingDecodedURL);
    request.setAttribute(LOOKUP_PATH_FOR_REQUEST, lookupPathForRequest);
    request.setAttribute(ORIGINATING_QUERY_STRING, originatingQueryString);

    logger.debug("postProcessPage(HttpServletRequest, int[], PagedListHandler, boolean) - end");
  }

  /** 取得当前页和记录索引 */
  public int[] getIndex(HttpServletRequest request) {
    if (isFirstPage(request)) return new int[]{0,0};
    return preProcessPage(request);
  }

  @Deprecated
  public final <T>ModelAndView processPage(PagedListHandler<T> currentPage, String pageAttributeKey, HttpServletRequest request) {
    this.currentPage = currentPage;
    request.setAttribute(pageAttributeKey, currentPage.getPageList());
    return this.handleRequest(request, null);
  }
  
  public final <T>ModelAndView processPage(PagedListHandler<T> currentPage, HttpServletRequest request) {
    this.currentPage = currentPage;
    return this.handleRequest(request, null);
  }

  protected PagedListHandler<T> processPage(HttpServletRequest request, HttpServletResponse response, int targetPageIndex, int recordStartIndex)  {
    return currentPage;
  }

  public static boolean isFirstPage(HttpServletRequest request) {
    return (request.getParameter("pageDirection") == null && request.getParameterValues("nextPageIndex") == null);
  }

  /** 判断一个请求是否为一个可根据任意页面进行查询的分页查询请求 */
  public static boolean isAnyPageSearch(HttpServletRequest request) {
    return !isFirstPage(request);
  }
}
